home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / tcl / tclm_1_0.lha / tclm-1.0 / MLIB / mfileutil.c < prev    next >
C/C++ Source or Header  |  1993-08-16  |  21KB  |  925 lines

  1. /*-
  2.  * Copyright (c) 1993 Michael B. Durian.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  * 3. All advertising materials mentioning features or use of this software
  13.  *    must display the following acknowledgement:
  14.  *    This product includes software developed by Michael B. Durian.
  15.  * 4. The name of the the Author may be used to endorse or promote 
  16.  *    products derived from this software without specific prior written 
  17.  *    permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  20.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  23.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29.  * SUCH DAMAGE.
  30.  */
  31. /*
  32.  * mfileutil.c,v 1.13 1993/05/07 17:45:18 durian Exp
  33.  */
  34. static char cvsid[] = "mfileutil.c,v 1.13 1993/05/07 17:45:18 durian Exp";
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <unistd.h>
  39. #include <string.h>
  40. #include <sys/fcntl.h>
  41. #include "mutil.h"
  42.  
  43. /* hack so we know if a read failed because of an eof instead of bad data */
  44. int MidiEof = 0;
  45. char MidiError[256];
  46.  
  47. int
  48. read_header_chunk(mfile, hchunk)
  49.     int mfile;
  50.     HCHUNK *hchunk;
  51. {
  52.  
  53.     if (mread(mfile, hchunk->str, sizeof(hchunk->str)) !=
  54.         sizeof(hchunk->str)) {
  55.         if (!MidiEof)
  56.             sprintf(MidiError,
  57.                 "Couldn't read header chunk identifier");
  58.         return (0);
  59.     }
  60.  
  61.     if (mread(mfile, (char *)&hchunk->length, sizeof(hchunk->length)) !=
  62.         sizeof(hchunk->length)) {
  63.         sprintf(MidiError, "Couldn't read header chunk length");
  64.         return (0);
  65.     }
  66.  
  67.     if (mread(mfile, (char *)&hchunk->format, sizeof(hchunk->format)) !=
  68.         sizeof(hchunk->format)) {
  69.         sprintf(MidiError, "Couldn't read header chunk format");
  70.         return (0);
  71.     }
  72.  
  73.     if (mread(mfile, (char *)&hchunk->num_trks, sizeof(hchunk->num_trks))
  74.         != sizeof(hchunk->num_trks)) {
  75.         sprintf(MidiError, "Couldn't read header chunk num_trks");
  76.         return (0);
  77.     }
  78.  
  79.     if (mread(mfile, (char *)&hchunk->division, sizeof(hchunk->division))
  80.         != sizeof(hchunk->division)) {
  81.         sprintf(MidiError, "Couldn't read header chunk division");
  82.         return (0);
  83.     }
  84.  
  85.     /* fix byte ordering */
  86.     hchunk->length = mtohl(hchunk->length);
  87.     hchunk->format = mtohs(hchunk->format);
  88.     hchunk->num_trks = mtohs(hchunk->num_trks);
  89.     hchunk->division = mtohs(hchunk->division);
  90.  
  91.     if (strncmp(hchunk->str, "MThd", 4) != 0) {
  92.         sprintf(MidiError, "Not a standard MIDI file");
  93.         return (0);
  94.     }
  95.  
  96.     if (hchunk->length != 6) {
  97.         sprintf(MidiError, "Bad header chunk size");
  98.         return (0);
  99.     }
  100.  
  101.     if (hchunk->format == 0 && hchunk->num_trks != 1) {
  102.         sprintf(MidiError,
  103.             "Midi format 0, but number of tracks (%d) is > 1",
  104.             hchunk->num_trks);
  105.         return (0);
  106.     }
  107.  
  108.     return (1);
  109. }
  110.  
  111. int
  112. read_track_chunk(mfile, tracks)
  113.     int mfile;
  114.     TCHUNK *tracks;
  115. {
  116.  
  117.     if (mread(mfile, tracks->str, 4) != 4) {
  118.         sprintf(MidiError, "Couldn't read track chunk identifier");
  119.         return (0);
  120.     }
  121.  
  122.     if (strncmp(tracks->str, "MTrk", 4) != 0) {
  123.         sprintf(MidiError, "Bad track chunk identifier");
  124.         return (0);
  125.     }
  126.  
  127.     if (mread(mfile, (char *)&tracks->length, sizeof(tracks->length)) !=
  128.         sizeof(tracks->length)) {
  129.         sprintf(MidiError, "Couldn't read track length");
  130.         return (0);
  131.     }
  132.  
  133.     tracks->msize = tracks->length = mtohl(tracks->length);
  134.     tracks->pos = 0;
  135.  
  136.     /* allocate space for tracks events */
  137.     if ((tracks->events = (unsigned char *) malloc(tracks->length)) ==
  138.         NULL) {
  139.         sprintf(MidiError, "Not enough memory for track data");
  140.         return (0);
  141.     }
  142.     tracks->event_start = tracks->events;
  143.  
  144.     if (mread(mfile, (char *)tracks->events, tracks->length) !=
  145.         tracks->length) {
  146.             sprintf(MidiError, "Couldn't read track data");
  147.             return (0);
  148.     }
  149.     tracks->events = tracks->event_start;
  150.  
  151.     return (1);
  152. }
  153.  
  154. int
  155. skip_track_chunk(mfile)
  156.     int mfile;
  157. {
  158.     long length;
  159.     char str[4];
  160.  
  161.     if (mread(mfile, str, sizeof(str)) != sizeof(str)) {
  162.         sprintf(MidiError, "Couldn't read track chunk identifier");
  163.         return (0);
  164.     }
  165.  
  166.     if (strncmp(str, "MTrk", 4) != 0) {
  167.         sprintf(MidiError, "Bad track chunk identifier");
  168.         return (0);
  169.     }
  170.  
  171.     if (mread(mfile, (char *)&length, sizeof(length)) != sizeof(length)) {
  172.         sprintf(MidiError, "Couldn't read track length");
  173.         return (0);
  174.     }
  175.  
  176.     length = mtohl(length);
  177.  
  178.     if (lseek(mfile, length, SEEK_CUR) == -1) {
  179.         sprintf(MidiError, "Couldn't seek past track");
  180.         return (0);
  181.     }
  182.  
  183.     return (1);
  184. }
  185.  
  186. int
  187. split_type_zero(tracks)
  188.     TCHUNK *tracks;
  189. {
  190.     long tempo_delta;
  191.     long data_delta;
  192.     long timing;
  193.     EVENT_TYPE event_type;
  194.     int data_size;
  195.     int event_size;
  196.     int i;
  197.     int offset;
  198.     int malloced_data;
  199.     int malloced_tempo;
  200.     int malloc_inc;
  201.     int tempo_size;
  202.     int time_len;
  203.     unsigned char event[256];
  204.     unsigned char *data_events;
  205.     unsigned char *data_ptr;
  206.     unsigned char *last_events;
  207.     unsigned char *tempo_events;
  208.     unsigned char *tempo_ptr;
  209.     unsigned char var_time[4];
  210.  
  211.     data_size = 0;
  212.     tempo_size = 0;
  213.     tempo_delta = 0;
  214.     data_delta = 0;
  215.     malloc_inc = 512;
  216.  
  217.     if ((data_events = (unsigned char *) malloc(malloc_inc))
  218.             == NULL) {
  219.         sprintf(MidiError, "Not enought memory to split track");
  220.         return (0);
  221.     }
  222.     malloced_data = malloc_inc;
  223.     if ((tempo_events = (unsigned char *) malloc(malloc_inc))
  224.             == NULL) {
  225.         sprintf(MidiError, "Not enought memory to split track");
  226.         return (0);
  227.     }
  228.     malloced_tempo = malloc_inc;
  229.  
  230.     data_ptr = data_events;
  231.     tempo_ptr = tempo_events;
  232.     while (event_size = get_smf_event(&tracks[0], event, &event_type)) {
  233.         if (event_size == -1) {
  234.             sprintf(MidiError,
  235.                 "Problem getting event while splitting");
  236.             return (0);
  237.         }
  238.  
  239.         if (event_type ==  NORMAL || event_type == SYSEX) {
  240.             timing = var2fix(event, &offset);
  241.             data_delta += timing;
  242.             time_len = fix2var(data_delta, var_time);
  243.             data_size += event_size - offset + time_len;
  244.             if (data_size > malloced_data) {
  245.                 last_events = data_events;
  246.                 if (!more_memory((char **)&data_events,
  247.                     malloced_data + malloc_inc)) {
  248.                     sprintf(MidiError,
  249.                         "Not enough memory");
  250.                     return (0);
  251.                 }
  252.                 if (data_events != last_events)
  253.                     data_ptr = data_events + (data_ptr -
  254.                         last_events);
  255.             }
  256.             /* copy in timing */
  257.             for (i = 0; i < time_len; i++)
  258.                 *data_ptr++ = var_time[i];
  259.  
  260.             /* copy in data */
  261.             for (i = offset; i < event_size; i++)
  262.                 *data_ptr++ = event[i];
  263.  
  264.             /* add timing to tempo delta */
  265.             tempo_delta += timing;
  266.             data_delta = 0;
  267.         } else {
  268.             timing = var2fix(event, &offset);
  269.             tempo_delta += timing;
  270.             time_len = fix2var(tempo_delta, var_time);
  271.             tempo_size += event_size - offset + time_len;
  272.             if (tempo_size > malloced_tempo) {
  273.                 last_events = tempo_events;
  274.                 if (!more_memory((char **)&tempo_events,
  275.                     malloced_tempo + malloc_inc)) {
  276.                     sprintf(MidiError,
  277.                         "Not enough memory");
  278.                     return (0);
  279.                 }
  280.                 if (tempo_events != last_events)
  281.                     tempo_ptr = data_events + (tempo_ptr -
  282.                         last_events);
  283.             }
  284.             /* copy in timing */
  285.             for (i = 0; i < time_len; i++)
  286.                 *tempo_ptr++ = var_time[i];
  287.  
  288.             /* copy in data */
  289.             for (i = offset; i < event_size; i++)
  290.                 *tempo_ptr++ = event[i];
  291.  
  292.             /* add timing to tempo delta */
  293.             data_delta += timing;
  294.             tempo_delta = 0;
  295.         }
  296.     }
  297.  
  298.     /* add eot to tempo track */
  299.     event[0] = 0xff;
  300.     event[1] = METAEOT;
  301.     event[2] = 0;
  302.     event_size = 3;
  303.  
  304.     time_len = fix2var(tempo_delta, var_time);
  305.     tempo_size += event_size + time_len;
  306.     if (tempo_size > malloced_tempo) {
  307.         last_events = tempo_events;
  308.         if (!more_memory((char **)&tempo_events, malloced_tempo +
  309.             malloc_inc)) {
  310.             sprintf(MidiError, "Not enough memory");
  311.             return (0);
  312.         }
  313.         if (tempo_events != last_events)
  314.             tempo_ptr = data_events + (tempo_ptr - last_events);
  315.     }
  316.     /* copy in timing */
  317.     for (i = 0; i < time_len; i++)
  318.         *tempo_ptr++ = var_time[i];
  319.  
  320.     /* copy in data */
  321.     for (i = 0; i < event_size; i++)
  322.         *tempo_ptr++ = event[i];
  323.             
  324.     free(tracks[0].events);
  325.     tracks[0].events = tracks[0].event_start = tempo_events;
  326.     tracks[1].events = tracks[1].event_start = data_events;
  327.     tracks[0].msize = malloced_tempo;
  328.     tracks[1].msize = malloced_data;
  329.     tracks[0].length = tempo_size;
  330.     tracks[1].length = data_size;
  331.     tracks[0].pos = 0;
  332.     tracks[1].pos = 0;
  333.     (void) strncpy(tracks[0].str, "MTrk", 4);
  334.     (void) strncpy(tracks[1].str, "MTrk", 4);
  335.     return (1);
  336. }
  337.  
  338. int
  339. more_memory(ptr, size)
  340.     char **ptr;
  341.     int size;
  342. {
  343.  
  344.     if ((*ptr = realloc(*ptr, size)) == NULL)
  345.         return (0);
  346.     else
  347.         return (1);
  348. }
  349.  
  350. int
  351. get_smf_event(track, event, event_type)
  352.     TCHUNK *track;
  353.     unsigned char *event;
  354.     EVENT_TYPE *event_type;
  355. {
  356.     long length = 0;
  357.     int i;
  358.     int size;
  359.     static int extra_bytes[] = {2, 2, 2, 2, 1, 1, 2, 0};
  360.     unsigned char etype;
  361.             
  362.     if (track->pos >= track->length)
  363.         return (0);
  364.  
  365.     /*
  366.      * get timing bytes
  367.      */
  368.     if (track->pos++ == track->length)
  369.         return (-1);
  370.     *event++ = *track->events++;
  371.     size = 1;
  372.     while (*(event - 1) & 0x80) {
  373.         if (track->pos++ == track->length)
  374.             return (-1);
  375.         *event++ = *track->events++;
  376.         size++;
  377.     }
  378.  
  379.     if (track->pos++ == track->length)
  380.         return (-1);
  381.     *event = *track->events++;
  382.  
  383.     /* get event type */
  384.     switch (*event) {
  385.     case 0xff:
  386.         /* meta event */
  387.         if (track->pos++ == track->length)
  388.             return (-1);
  389.         size++;
  390.         event++;
  391.         *event_type = *event++ = *track->events++;
  392.         size++;
  393.         /* get length as a variable length */
  394.         do {
  395.             if (track->pos++ == track->length)
  396.                 return (-1);
  397.             length = (length << 7) + (*track->events & 0x7f);
  398.             *event = *track->events++;
  399.             size++;
  400.         } while (*event++ & 0x80);
  401.         for (; length > 0; length--) {
  402.             /* get event */
  403.             if (track->pos++ == track->length)
  404.                 return (-1);
  405.             *event++ = *track->events++;
  406.             size++;
  407.         }
  408.         track->read_rs = 0;
  409.         break;
  410.     case 0xf0:
  411.     case 0xf7:
  412.         event++;
  413.         size++;
  414.         *event_type = SYSEX;
  415.         /* get length as variable length value */
  416.         do {
  417.             if (track->pos++ == track->length)
  418.                 return (-1);
  419.             length = (length << 7) + (*track->events & 0x7f);
  420.             *event = *track->events++;
  421.             size++;
  422.         } while (*event++ & 0x80);
  423.         for (; length > 0; length--) {
  424.             /* get event */
  425.             if (track->pos++ == track->length)
  426.                 return (-1);
  427.             *event++ = *track->events++;
  428.             size++;
  429.         }
  430.         track->read_rs = 0;
  431.         break;
  432.     default:
  433.         *event_type = NORMAL;
  434.         size++;
  435.         if (*event & 0x80) {
  436.             etype = *event;
  437.             track->read_rs = etype;
  438.             for (i = 0; i < extra_bytes[(etype >> 4) & 0x07];
  439.                 i++) {
  440.                 event++;
  441.                 if (track->pos++ == track->length)
  442.                     return(-1);
  443.                 *event = *track->events++;
  444.                 size++;
  445.             }
  446.         } else {
  447.             /* it is using running state */
  448.             /* get other data bytes */
  449.             switch ((track->read_rs >> 4) & 0x0f) {
  450.             case 0x08:
  451.             case 0x09:
  452.             case 0x0a:
  453.             case 0x0b:
  454.             case 0x0e:
  455.                 event++;
  456.                 if (track->pos++ == track->length)
  457.                     return (-1);
  458.                 *event = *track->events++;
  459.                 size++;
  460.                 break;
  461.             default:
  462.                 break;
  463.             }
  464.         }
  465.     }
  466.     return (size);
  467. }
  468.  
  469. int
  470. put_smf_event(track, event, event_size)
  471.     TCHUNK *track;
  472.     unsigned char *event;
  473.     int event_size;
  474. {
  475.     unsigned char *event_cpy;
  476.     unsigned char *event_ptr;
  477.     int i;
  478.     int pos;
  479.  
  480.     /* make a copy of the event we can modify */
  481.     if ((event_cpy = (unsigned char *)malloc(event_size)) == NULL) {
  482.         sprintf(MidiError, "Out of memory in put_smf_event");
  483.         return (0);
  484.     }
  485.     for (i = 0; i < event_size; i++)
  486.         event_cpy[i] = event[i];
  487.  
  488.     /* skip timing part */
  489.     (void)var2fix(event_cpy, &pos);
  490.     event_ptr = event_cpy + pos;
  491.  
  492.     /*
  493.      * check event type to see if we can dump the running state
  494.      * If there is no running state, assume whoever sent us
  495.      * the data got it right.
  496.      */
  497.     if (*event_ptr & 0x80) {
  498.         switch (*event_ptr & 0xf0) {
  499.         case 0xf0:
  500.             /* clear running state for these */
  501.             track->write_rs = 0;
  502.             break;
  503.         default:
  504.             if (*event_ptr != track->write_rs)
  505.                 track->write_rs = *event_ptr;
  506.             else {
  507.                 /* it's the same as the last, so dump it */
  508.                 event_size--;
  509.                 while (pos++ < event_size) {
  510.                     *event_ptr = *(event_ptr + 1);
  511.                     event_ptr++;
  512.                 }
  513.             }
  514.         }
  515.     }
  516.     if (track->msize == 0) {
  517.         if ((track->event_start = (unsigned char *)malloc(
  518.             BUFSIZ)) == NULL) {
  519.             sprintf(MidiError, "Not enough memory for new event");
  520.             return (0);
  521.         }
  522.         track->msize = BUFSIZ;
  523.         track->events = track->event_start;
  524.     }
  525.     track->length += event_size;
  526.     if (track->length > track->msize) {
  527.         track->msize += BUFSIZ;
  528.         if ((track->event_start =
  529.             (unsigned char *)realloc(track->event_start, track->msize))
  530.             == NULL) {
  531.             perror("");
  532.             sprintf(MidiError, "Not enough memory for new event");
  533.             track->length -= event_size;
  534.             track->msize -= BUFSIZ;
  535.             return (0);
  536.         }
  537.         /* starting position might move */
  538.         track->events = track->event_start + track->pos;
  539.     }
  540.  
  541.     memcpy(track->event_start + track->length - event_size, event_cpy,
  542.         event_size);
  543.     free(event_cpy);
  544.     return (1);
  545. }
  546.  
  547. void
  548. rewind_track(track)
  549.     TCHUNK *track;
  550. {
  551.     track->pos = 0;
  552.     track->events = track->event_start;
  553.     track->read_rs = 0;
  554. }
  555.  
  556. void
  557. reset_track(track)
  558.     TCHUNK *track;
  559. {
  560.     track->pos = 0;
  561.     track->length = 0;
  562.     track->events = track->event_start;
  563.     track->read_rs = 0;
  564.     track->write_rs = 0;
  565. }
  566.  
  567.  
  568. int
  569. write_header_chunk(mfile, hchunk)
  570.     int mfile;
  571.     HCHUNK *hchunk;
  572. {
  573.  
  574.     (void)strncpy(hchunk->str, "MThd", 4);
  575.     if (mwrite(mfile, hchunk->str, 4) != 4) {
  576.         sprintf(MidiError, "Couldn't write header chunk identifier");
  577.         return (0);
  578.     }
  579.  
  580.     hchunk->length = 6;
  581.     hchunk->length = htoml(hchunk->length);
  582.     if (mwrite(mfile, (char *)&hchunk->length, sizeof(hchunk->length)) !=
  583.         sizeof(hchunk->length)) {
  584.         sprintf(MidiError, "Couldn't write header chunk length");
  585.         return (0);
  586.     }
  587.     hchunk->length = mtohl(hchunk->length);
  588.  
  589.     hchunk->format = htoms(hchunk->format);
  590.     if (mwrite(mfile, (char *)&hchunk->format, sizeof(hchunk->format)) !=
  591.         sizeof(hchunk->format)) {
  592.         sprintf(MidiError, "Couldn't write header chunk format");
  593.         return (0);
  594.     }
  595.     hchunk->format = mtohs(hchunk->format);
  596.  
  597.     hchunk->num_trks = htoms(hchunk->num_trks);
  598.     if (mwrite(mfile, (char *)&hchunk->num_trks, sizeof(hchunk->num_trks))
  599.         != sizeof(hchunk->num_trks)) {
  600.         sprintf(MidiError, "Couldn't write number of tracks");
  601.         return (0);
  602.     }
  603.     hchunk->num_trks = mtohs(hchunk->num_trks);
  604.  
  605.     hchunk->division = htoms(hchunk->division);
  606.     if (mwrite(mfile, (char *)&hchunk->division, sizeof(hchunk->division))
  607.         != sizeof(hchunk->division)) {
  608.         sprintf(MidiError, "Couldn't write header chunk division");
  609.         return (0);
  610.     }
  611.     hchunk->division = mtohs(hchunk->division);
  612.  
  613.     return (1);
  614. }
  615.  
  616. int
  617. write_track_chunk(mfile, tchunk)
  618.     int mfile;
  619.     TCHUNK *tchunk;
  620. {
  621.     long midi_length;
  622.  
  623.     (void)strncpy(tchunk->str, "MTrk", 4);
  624.     if (mwrite(mfile, tchunk->str, 4) != 4) {
  625.         sprintf(MidiError, "Couldn't write track chunk identifier");
  626.         return (0);
  627.     }
  628.  
  629.     midi_length = htoml(tchunk->length);
  630.     if (mwrite(mfile, (char *)&midi_length, sizeof(midi_length)) !=
  631.         sizeof(midi_length)) {
  632.         sprintf(MidiError, "Couldn't write track length");
  633.         return (0);
  634.     }
  635.  
  636.     if (mwrite(mfile, (char *)tchunk->event_start, tchunk->length)
  637.         != tchunk->length) {
  638.         sprintf(MidiError, "Couldn't write track events");
  639.         return (0);
  640.     }
  641.  
  642.     return (1);
  643. }
  644.  
  645. int
  646. merge_tracks(out, in, tscalar, num, delta)
  647.     TCHUNK *out;
  648.     TCHUNK **in;
  649.     int *tscalar;
  650.     int num;
  651.     int delta;
  652. {
  653.     struct evnt {
  654.         long    timing;
  655.         EVENT_TYPE    type;
  656.         int    size;
  657.         short    remainder;
  658.         unsigned    char event[256];
  659.         unsigned    char run_state;
  660.     } *ev;
  661.     long timing;
  662.     int *atracks;
  663.     int endtime;
  664.     int i;
  665.     int j;
  666.     int foo;
  667.     int lasttime;
  668.     int next;
  669.     int num_active;
  670.     unsigned char event[256];
  671.  
  672.     if ((ev = (struct evnt *)malloc(sizeof(struct evnt) * num))
  673.         == NULL) {
  674.         sprintf(MidiError, "Not enough memory for event buffers");
  675.         return (-1);
  676.     }
  677.     if ((atracks = (int *)malloc(sizeof(int) * num)) == NULL) {
  678.         sprintf(MidiError, "Not enought memory for atracks");
  679.         free((char *)ev);
  680.         return (-1);
  681.     }
  682.  
  683.     endtime = delta;
  684.     /* get first events from each in track */
  685.     for (i = 0; i < num; i++) {
  686.         if ((ev[i].size = get_smf_event(in[i], ev[i].event,
  687.             &ev[i].type)) == -1) {
  688.             free((char *)ev);
  689.             free((char *)atracks);
  690.             return (-1);
  691.         }
  692.         ev[i].run_state = get_running_state(in[i]);
  693.  
  694.         /* convert time */
  695.         timing = var2fix(ev[i].event, &foo);
  696.         ev[i].timing = timing / tscalar[i] + delta;
  697.         ev[i].remainder = timing % tscalar[i];
  698.         /* alway force inclusion of running status */
  699.         ev[i].size -= foo;
  700.         for (j = 0; j < ev[i].size; j++)
  701.             ev[i].event[j] = ev[i].event[foo + j];
  702.         if (ev[i].type == METAEOT) {
  703.             if (ev[i].timing > endtime)
  704.                 endtime = ev[i].timing;
  705.         } else
  706.             atracks[i] = 1;
  707.     }
  708.     num_active = num;
  709.  
  710.     lasttime = 0;
  711.     while (num_active) {
  712.         /* find first active track */
  713.         next = 0;
  714.         for (i = 0; i < num; i++)
  715.             if (atracks[i]) {
  716.                 next = i;
  717.                 break;
  718.             }
  719.         /* now compare to find active track with smallest timing */
  720.         for (; i < num; i++)
  721.             if (atracks[i])
  722.                 if (ev[i].timing < ev[next].timing)
  723.                     next = i;
  724.  
  725.         foo = fix2var(ev[next].timing - lasttime, event);
  726.  
  727.         /* stick in a running state if it is missing */
  728.         if (!(ev[next].event[0] & 0x80))
  729.             event[foo++] = ev[next].run_state;
  730.  
  731.         for (i = 0; i < ev[next].size; i++)
  732.             event[foo + i] = ev[next].event[i];
  733.  
  734. /*
  735. {
  736. int x;
  737. printf("wrote: ");
  738. for (x = 0; x < ev[next].size + foo; x++)
  739. printf("0x%02x ", event[x]);
  740. printf("\n");
  741. }
  742. */
  743.  
  744.         /* change timing value of event */
  745.         if (!put_smf_event(out, event, ev[next].size + foo)) {
  746.             free((char *)ev);
  747.             free((char *)atracks);
  748.             return (-1);
  749.         }
  750.  
  751.         lasttime = ev[next].timing;
  752.  
  753.         /* get replacement event */
  754.         if ((ev[next].size = get_smf_event(in[next], ev[next].event,
  755.             &ev[next].type)) == -1) {
  756.             free((char *)ev);
  757.             free((char *)atracks);
  758.             return (-1);
  759.         }
  760. /*
  761. {
  762. int x;
  763. printf("read: ");
  764. for (x = 0; x < ev[next].size; x++)
  765. printf("0x%02x ", ev[next].event[x]);
  766. printf("\n");
  767. }
  768. */
  769.         ev[next].run_state = get_running_state(in[next]);
  770.         /* convert time */
  771.         timing = var2fix(ev[next].event, &foo) + ev[next].remainder;
  772.         ev[next].timing += timing / tscalar[next];
  773.         ev[next].remainder = timing % tscalar[next];
  774.         ev[next].size -= foo;
  775.         for (j = 0; j < ev[next].size; j++)
  776.             ev[next].event[j] = ev[next].event[foo + j];
  777.         if (ev[next].type == METAEOT) {
  778.             if (ev[next].timing > endtime)
  779.                 endtime = ev[next].timing;
  780.             atracks[next] = 0;
  781.             num_active--;
  782.         }
  783.     }
  784.     free((char *)ev);
  785.     free((char *)atracks);
  786.     return (endtime - lasttime);
  787. }
  788.  
  789. int
  790. fix2var(val, ptr)
  791.     long val;
  792.     unsigned char *ptr;
  793. {
  794.     int i;
  795.     unsigned char buf[4];
  796.     unsigned char *bptr;
  797.  
  798.     buf[0] = buf[1] = buf[2] = buf[3] = 0;
  799.     bptr = buf;
  800.     *bptr++ = val & 0x7f;
  801.     while ((val >>= 7) > 0) {
  802.         *bptr |= 0x80;
  803.         *bptr++ += (val & 0x7f);
  804.     }
  805.  
  806.     i = 0;
  807.     do {
  808.         *ptr++ = *--bptr;
  809.         i++;
  810.     } while (bptr != buf);
  811.  
  812.     return (i);
  813. }
  814.  
  815. long
  816. var2fix(var, delta)
  817.     unsigned char *var;
  818.     int *delta;
  819. {
  820.     long fix;
  821.  
  822.     fix = 0;
  823.     *delta = 0;
  824.     if (*var & 0x80)
  825.         do {
  826.             fix = (fix << 7) + (*var & 0x7f);
  827.             (*delta)++;
  828.         } while (*var++ & 0x80);
  829.     else {
  830.         fix = *var++;
  831.         (*delta)++;
  832.     }
  833.  
  834.     return (fix);
  835. }
  836.  
  837. void
  838. free_track(track)
  839.     TCHUNK *track;
  840. {
  841.  
  842.     if (track == NULL)
  843.         return;
  844.     if (track->event_start != NULL)
  845.         free(track->event_start);
  846.     track->event_start = NULL;
  847.     track->events = NULL;
  848.     track->length = 0;
  849.     track->pos = 0;
  850.     track->msize = 0;
  851.     track->read_rs = 0;
  852.     track->write_rs = 0;
  853. }
  854.  
  855. void
  856. init_track(track)
  857.     TCHUNK *track;
  858. {
  859.     track->event_start = NULL;
  860.     track->events = NULL;
  861.     track->msize = 0;
  862.     track->length = 0;
  863.     track->pos = 0;
  864.     track->read_rs = 0;
  865.     track->write_rs = 0;
  866.     strncpy(track->str, "MTrk", 4);
  867. }
  868.  
  869. unsigned char
  870. get_running_state(track)
  871.     TCHUNK *track;
  872. {
  873.  
  874.     return (track->read_rs);
  875. }
  876.  
  877. int
  878. mread(dev, buf, size)
  879.     int dev;
  880.     char *buf;
  881.     int size;
  882. {
  883.     int num_read;
  884.     int total_read;
  885.  
  886.     total_read = 0;
  887.     do {
  888.         if ((num_read = read(dev, buf, size - total_read)) == -1) {
  889.             perror("");
  890.             return (-1);
  891.         }
  892.         if (num_read == 0)
  893.             break;
  894.         total_read += num_read;
  895.         buf += num_read;
  896.     } while (size > total_read);
  897.     if (total_read == 0)
  898.         MidiEof = 1;
  899.     return (total_read);
  900. }
  901.  
  902. int
  903. mwrite(dev, buf, size)
  904.     int dev;
  905.     char *buf;
  906.     int size;
  907. {
  908.     int num_written;
  909.     int total_written;
  910.  
  911.     total_written = 0;
  912.     do {
  913.         if ((num_written = write(dev, buf, size - total_written))
  914.             == -1) {
  915.             perror("");
  916.             return (-1);
  917.         }
  918.         if (num_written == 0)
  919.             break;
  920.         total_written += num_written;
  921.         buf += num_written;
  922.     } while (size > total_written);
  923.     return (total_written);
  924. }
  925.